// This File is part of the "nyaqt" Project
// 
// Copyright  2009 sometmes@gmail.com
// All rights reserved
// 
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.



using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using nyaqt.Plugins;

namespace nyaqt
{
    class NyaqtConnectionStringBuilder : nyaqt.Plugins.NyaqtConnectionStringBuilder
    {
        Dictionary<string, string> _keywords;

        public NyaqtConnectionStringBuilder(Dictionary<KnownNyaqtConnectionKeys,string> knownKeywords, Dictionary<string,string> keywordMap)
        {
            if (knownKeywords.Count != 4)
                throw new ArgumentException("All known keywords must be mapped");

            foreach (KeyValuePair<KnownNyaqtConnectionKeys, string> pair in knownKeywords)
            {
                CheckKnownKeyword(pair.Value, keywordMap);

                if (pair.Key == KnownNyaqtConnectionKeys.Server)
                    _serverKey = pair.Value;
                else if (pair.Key == KnownNyaqtConnectionKeys.Database)
                    _databaseKey = pair.Value;
                else if (pair.Key == KnownNyaqtConnectionKeys.Login)
                    _loginKey = pair.Value;
                else if (pair.Key == KnownNyaqtConnectionKeys.Password)
                    _passwordKey = pair.Value;
            }

            _keywords = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            foreach (KeyValuePair<string,string> pair in keywordMap)
            {
                _keywords[pair.Key] = pair.Value;
            }
        }

        private NyaqtConnectionStringBuilder()
        {
        }

        void CheckKnownKeyword(string knownKeyword, Dictionary<string, string> keywordMap)
        {
            if (keywordMap[knownKeyword] != knownKeyword)
                throw new ArgumentException("Known keywords must meet mapped keywords");
        }

        string MapKeyword(string keyword)
        {
            if (!_keywords.ContainsKey(keyword))
                return keyword;
            else
                return _keywords[keyword];
        }

        public override object this[string keyword]
        {
            get
            {
                string mappedKey = MapKeyword(keyword);
                if (!string.Equals(keyword, mappedKey,StringComparison.OrdinalIgnoreCase) && this.ContainsKey(keyword) && this.ContainsKey(mappedKey))
                    throw new SystemException("System exception, two synonym keywords present");

                if (this.ContainsKey(mappedKey))
                    return base[mappedKey];
                return null;
            }
            set
            {
                string mappedKey = MapKeyword(keyword);
                if (!string.Equals(keyword, mappedKey, StringComparison.OrdinalIgnoreCase) && this.ContainsKey(keyword) && this.ContainsKey(mappedKey))
                    throw new SystemException("System exception, two synonym keywords present");
                if (keyword != mappedKey && !this.ContainsKey(mappedKey))
                    mappedKey = ChangePreferredKeyword(mappedKey, keyword);

                base[keyword] = value;
            }

        }

        private string ChangePreferredKeyword(string mappedKey, string keyword)
        {
            List<string> toremap = new List<string>();
            foreach (KeyValuePair<string, string> pair in _keywords)
            {
                if (pair.Value.Equals(mappedKey,StringComparison.OrdinalIgnoreCase))
                    toremap.Add(pair.Key);
            }

            foreach (string key in toremap)
            {
                string current = _keywords[key];
                if (current == _serverKey)
                    _serverKey = keyword;
                if (current == _databaseKey)
                    _databaseKey = keyword;
                if (current == _loginKey)
                    _loginKey = keyword;
                if (current == _passwordKey)
                    _passwordKey = keyword;

                _keywords[key] = keyword;
            }
            return keyword;
        }

        string _serverKey = "Data Source";
        public override string Server
        {
            get { return (string) this[_serverKey]; }
            set { this[_serverKey] = value; }
        }

        string _databaseKey = "Initial Catalog";
        public override string Database
        {
            get { return (string)this[_databaseKey]; }
            set { this[_databaseKey] = value; }
        }

        string _loginKey = "User ID";
        public override string Login
        {
            get { return (string)this[_loginKey]; }
            set { this[_loginKey] = value; }
        }

        string _passwordKey = "Password";
        public override string Password
        {
            get { return (string)this[_passwordKey]; }
            set { this[_passwordKey] = value; }
        }

        public override nyaqt.Plugins.NyaqtConnectionStringBuilder Copy()
        {
            NyaqtConnectionStringBuilder builder = new NyaqtConnectionStringBuilder();
            builder._keywords = new Dictionary<string, string>(this._keywords);
            builder._serverKey = this._serverKey;
            builder._databaseKey = this._databaseKey;
            builder._loginKey = this._loginKey;
            builder._passwordKey = this._passwordKey;
            builder.ConnectionString = this.ConnectionString;
            return builder;
        }
    }
}
































